﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Controls.Maps;
using System.Device.Location;
using Rally_like_a_madman.Data;
using System.Windows.Threading;

namespace Rally_like_a_madman
{
    public partial class NavigationPage : PhoneApplicationPage
    {
        private static readonly int DEFAULT_ZOOM_LEVEL = 16;
        private static readonly int MAX_DISTANCE_FROM_WAYPOINT = 25;

        GeoCoordinateWatcher geoCoordinateWatcher;
        MapLayer pushPinLayer;
        Pushpin userPushPin;
        DispatcherTimer rallyTimer;
        List<GeoCoordinate> allLocations = new List<GeoCoordinate>();

        public NavigationPage()
        {
            InitializeComponent();

            rallyTimer = new DispatcherTimer();
            rallyTimer.Interval = TimeSpan.FromSeconds(1);
            rallyTimer.Tick += OnTimerTick; 
            rallyTimer.Start();

            geoCoordinateWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
            geoCoordinateWatcher.PositionChanged += geoCoordinateWatcherPositionChanged;
            geoCoordinateWatcher.Start();

            pushPinLayer = new MapLayer();
            userPushPin = new Pushpin();

            pushPinLayer.AddChild(userPushPin, new GeoCoordinate(0, 0));

            map.ZoomLevel = DEFAULT_ZOOM_LEVEL;
            map.Children.Add(pushPinLayer);
            updateUserPushpin(51.5870, 004.7786);

            redrawMap();
        }

        void OnTimerTick(Object sender, EventArgs args)
        {
            TimeSpan walkedTime = DateTime.Now - NavigationHelper.GetStartTime();
            tbTime.Text = walkedTime.ToString(@"hh\:mm\:ss");
        }

        private void redrawMap()
        {
            allLocations.Clear();
            pushPinLayer.Children.Clear();

            pushPinLayer.AddChild(userPushPin, userPushPin.Location);

            foreach (RouteWaypointLink wayPointLink in NavigationHelper.GetAllWaypointsLinksOnCurrentRoute())
            {
                Pushpin pin = new Pushpin();
                pin.Content = "" + (wayPointLink.WaypointIndex + 1);
                pin.Background = new SolidColorBrush(Colors.Blue);

                GeoCoordinate waypointCoords = new GeoCoordinate(wayPointLink.Waypoint.GPSLatitude, wayPointLink.Waypoint.GPSLongitude);
                pin.Location = waypointCoords;

                pushPinLayer.AddChild(pin, waypointCoords);
                allLocations.Add(waypointCoords);
            }

            map.Center = new GeoCoordinate(userPushPin.Location.Latitude, userPushPin.Location.Longitude);
        }

        private void geoCoordinateWatcherPositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            var currentLatitude = e.Position.Location.Latitude;
            var currentLongitude = e.Position.Location.Longitude;

            updateUserPushpin(currentLatitude, currentLongitude);

            redrawMap();
        }

        private void updateUserPushpin(Double latitude, Double longitude)
        {
            GeoCoordinate userLocation = new GeoCoordinate(latitude, longitude);
            userPushPin.Location = userLocation;

            if (NavigationHelper.GetNextWaypointOnRoute() == null)
                return;

            double nextWaypointLatitude = NavigationHelper.GetNextWaypointOnRoute().GPSLatitude;
            double nextWaypointLongitude = NavigationHelper.GetNextWaypointOnRoute().GPSLongitude;
            GeoCoordinate nextWaypointLocation = new GeoCoordinate(nextWaypointLatitude, nextWaypointLongitude);

            if (userPushPin.Location.GetDistanceTo(nextWaypointLocation) < MAX_DISTANCE_FROM_WAYPOINT)
            {
                atNextWaypoint();
            }
        }

        private void atNextWaypoint()
        {
            if (!NavigationHelper.Next())
            {
                NavigationService.Navigate(new Uri("/EndOfRoutePage.xaml", UriKind.RelativeOrAbsolute));
                rallyTimer.Stop();
            }
        }
    }
}